import 'dart:async';
import 'dart:math';
import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'hero_bar_widget.dart';
import 'hero_image_swiper_plugin.dart';
import 'hero_widget.dart';

typedef DoubleClickAnimationListener = void Function();

/// 多图片滑动切换页面
class HeroSwiperImagePage extends StatefulWidget {
  const HeroSwiperImagePage({
    required this.index,
    required this.pics,
    this.onPageChanged,
  });
  final int index;
  final List<String> pics;
  final ValueChanged<int>? onPageChanged;
  @override
  _HeroSwiperImagePageState createState() => _HeroSwiperImagePageState();
}

class _HeroSwiperImagePageState extends State<HeroSwiperImagePage>
    with TickerProviderStateMixin {
  /// 控制pageController滑动事件
  final StreamController<int> rebuildIndex = StreamController<int>.broadcast();

  // 控制双击放大动画
  Animation<double>? _doubleClickAnimation;
  // 动画控制器
  AnimationController? _doubleClickAnimationController;
  DoubleClickAnimationListener? _doubleClickAnimationListener;
  List<double> doubleTapScales = <double>[1.0, 2.0, 3.0];

  GlobalKey<ExtendedImageSlidePageState> slidePagekey =
      GlobalKey<ExtendedImageSlidePageState>();

  /// 当前选中项
  int _currentIndex = 0;

  @override
  void initState() {
    _currentIndex = widget.index;
    _doubleClickAnimationController = AnimationController(
        duration: const Duration(milliseconds: 150), vsync: this);

    super.initState();
  }

  @override
  void dispose() {
    rebuildIndex.close();
    _doubleClickAnimationController?.dispose();
    clearGestureDetailsCache();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    Widget result = Stack(
      children: <Widget>[
        Positioned.fill(
          child: ExtendedImageGesturePageView.builder(
            controller: ExtendedPageController(
              initialPage: widget.index,
            ),
            itemBuilder: (BuildContext context, int index) {
              final String item = widget.pics[index];
              Widget image = ExtendedImage.network(
                item,
                fit: BoxFit.contain,
                // enableSlideOutPage: true,
                mode: ExtendedImageMode.gesture,
                loadStateChanged: _loadStateChanged,
                heroBuilderForSlidingPage: (Widget result) {
                  return result;
                },
                initGestureConfigHandler: _heroBuilderForSlidingPage,
                onDoubleTap: _onDoubleTap,
              );
              // image = GestureDetector(
              //   child: image,
              //   onTap: () {
              //     {
              //       slidePagekey.currentState?.popPage();
              //       Navigator.pop(context);
              //     }
              //   },
              // );
              return HeroWidget(
                child: image,
                tag: "$item-$index",
                slideType: SlideType.onlyImage,
                slidePagekey: slidePagekey,
              );
            },
            itemCount: widget.pics.length,
            onPageChanged: (int index) {
              _currentIndex = index;
              rebuildIndex.add(index);
              if (widget.onPageChanged != null) {
                widget.onPageChanged!.call(index);
              }
            },
            scrollDirection: Axis.horizontal,
            physics: const BouncingScrollPhysics(),
          ),
        ),
        Positioned(
          bottom: 0.0,
          left: 0.0,
          right: 0.0,
          child: HeroImageSwiperPlugin(
            widget.pics,
            _currentIndex,
            rebuildIndex,
          ),
        ),
        HeroBarWidget(
          reBuild: rebuildIndex,
          count: widget.pics.length,
          index: _currentIndex,
          onTap: () {
            slidePagekey.currentState?.popPage();
            Navigator.pop(context);
          },
        ),
      ],
    );

    result = Theme(
      data: Theme.of(context).copyWith(
        dialogBackgroundColor: Color(0xFF333333),
      ),
      child: ExtendedImageSlidePage(
        key: slidePagekey,
        child: result,
        slideAxis: SlideAxis.both,
        slideType: SlideType.onlyImage,
      ),
    );
    return result;
  }

  /// 图片加载, 可用于控制加载中,加载成功,加载失败时自定义布局
  Widget? _loadStateChanged(ExtendedImageState state) {
    Widget? childWidget;
    switch (state.extendedImageLoadState) {
      case LoadState.failed:
        childWidget = Image.asset(
          'assets/images/public/default.png',
          // fit: BoxFit.cover,
        );
        break;
      default:
        // 加载成功时与加载中使用默认布局
        break;
    }
    return childWidget;
  }

  /// 双击放大图片, 使用了动画放大方式
  ///
  /// 注意每次执行动画后需要重置双击动画相关参数
  void _onDoubleTap(ExtendedImageGestureState state) {
    // 你可以使用定义pointerDownPosition，
    // 默认值是双击指针向下的位置。
    // 用于控制双击后图片的位置
    final Offset? pointerDownPosition = state.pointerDownPosition;
    final double? begin = state.gestureDetails?.totalScale;
    double end;

    // 移除旧的双击动画监听
    _doubleClickAnimation?.removeListener(_doubleClickAnimationListener!);
    // 停止双击事件
    _doubleClickAnimationController?.stop();
    // 重置双击事件
    _doubleClickAnimationController?.reset();

    // 判断双击状态控制当前显示图片的大小
    if (begin == doubleTapScales[0]) {
      end = doubleTapScales[1];
    } else if (begin == doubleTapScales[1]) {
      end = doubleTapScales[2];
    } else {
      end = doubleTapScales[0];
    }
    // 重新设置双击动画监听
    _doubleClickAnimationListener = () {
      state.handleDoubleTap(
        scale: _doubleClickAnimation?.value,
        doubleTapPosition: pointerDownPosition,
      );
    };
    // 重置双击动画的值
    _doubleClickAnimation = _doubleClickAnimationController!
        .drive(Tween<double>(begin: begin, end: end));
    // 添加新的双击监听
    _doubleClickAnimation?.addListener(_doubleClickAnimationListener!);
    // 执行双击监听
    _doubleClickAnimationController?.forward();
  }

  GestureConfig _heroBuilderForSlidingPage(ExtendedImageState state) {
    final Size size = MediaQuery.of(context).size;
    double initialScale = 1.0;
    if (state.extendedImageInfo != null &&
        state.extendedImageInfo?.image != null) {
      initialScale = initScale(
          size: size,
          initialScale: initialScale,
          imageSize: Size(
              state.extendedImageInfo?.image.width.toDouble() ?? 0.0,
              state.extendedImageInfo?.image.height.toDouble() ?? 0.0));
    }
    return GestureConfig(
      inPageView: true,
      initialScale: initialScale,
      // minScale: initialScale,
      // animationMinScale: min(initialScale, 0.9),
      maxScale: max(initialScale, 5.0),
      animationMaxScale: max(initialScale, 5.0),
      initialAlignment: InitialAlignment.center,
      // 即使页面视图页面更改，也可以缓存手势状态。
      // 记住在正确的时间调用clearGestureDetailsCache()方法。(例如，该页面被处理)
      cacheGesture: false,
    );
  }
}

///
///  create by zmtzawqlp on 2020/1/31
///
double initScale(
    {required Size imageSize,
    required Size size,
    required double initialScale}) {
  final double n1 = imageSize.height / imageSize.width;
  final double n2 = size.height / size.width;
  if (n1 > n2) {
    final FittedSizes fittedSizes =
        applyBoxFit(BoxFit.contain, imageSize, size);
    //final Size sourceSize = fittedSizes.source;
    final Size destinationSize = fittedSizes.destination;
    return size.width / destinationSize.width;
  } else if (n1 / n2 < 1 / 4) {
    final FittedSizes fittedSizes =
        applyBoxFit(BoxFit.contain, imageSize, size);
    //final Size sourceSize = fittedSizes.source;
    final Size destinationSize = fittedSizes.destination;
    return size.height / destinationSize.height;
  }

  return initialScale;
}
